/*
- GlobalSat DG-100 GPS data logger download.
+ GlobalSat DG-100/DG-200 GPS data logger download.
Copyright (C) 2007 Mirko Parthey, mirko.parthey@informatik.tu-chemnitz.de
Copyright (C) 2005-2008 Robert Lipe, robertlipe+source@gpsbabel.org
Copyright (C) 2012 Nicolas Boullis, nboullis@debian.org
+ Copyright (C) 2014 Jean-Claude Repetto, gpsbabel@repetto.org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
/*
- DG-100 communication protocol specification:
- http://www.usglobalsat.com/forum/topic.asp?TOPIC_ID=607#1375
+ DG-100 / DG-200 communication protocol specification:
+ http://www.usglobalsat.com/s-176-developer-information.aspx
*/
#include "defs.h"
#define MYNAME "DG-100"
typedef struct {
+ const char *name;
unsigned speed;
int has_trailing_bytes;
int has_payload_end_seq;
+ struct dg100_command *commands;
+ unsigned int numcommands;
} model_t;
static const model_t* model;
dg100cmd_erase = 0xBA,
dg100cmd_getid = 0xBF,
dg100cmd_setid = 0xC0,
- dg100cmd_gpsmouse = 0xBC
+ dg100cmd_gpsmouse = 0xBC,
+ dg200cmd_reset = 0x80
};
struct dg100_command {
};
struct dg100_command dg100_commands[] = {
+ { dg100cmd_getfile, 2, 1024, 2, "getfile" },
+ /* the getfileheader answer has variable length, -1 is a dummy value */
+ { dg100cmd_getfileheader, 2, -1, 2, "getfileheader" },
+ { dg100cmd_erase, 2, 4, 2, "erase" },
{ dg100cmd_getconfig, 0, 44, 2, "getconfig" },
{ dg100cmd_setconfig, 41, 4, 2, "setconfig" },
+ { dg100cmd_getid, 0, 8, 2, "getid" },
+ { dg100cmd_setid, 8, 4, 2, "setid" },
+ { dg100cmd_gpsmouse, 1, 0, 0, "gpsmouse" }
+};
+
+struct dg100_command dg200_commands[] = {
+ { dg100cmd_getfile, 2, 1024, 2, "getfile" },
/* the getfileheader answer has variable length, -1 is a dummy value */
{ dg100cmd_getfileheader, 2, -1, 2, "getfileheader" },
- { dg100cmd_getfile, 2, 1024, 2, "getfile" },
{ dg100cmd_erase, 2, 4, 2, "erase" },
+ { dg100cmd_getconfig, 0, 45, 2, "getconfig" },
+ { dg100cmd_setconfig, 42, 4, 2, "setconfig" },
{ dg100cmd_getid, 0, 8, 2, "getid" },
{ dg100cmd_setid, 8, 4, 2, "setid" },
- { dg100cmd_gpsmouse, 1, 0, 0, "gpsmouse" }
+ { dg100cmd_gpsmouse, 1, 0, 0, "gpsmouse" },
+ { dg200cmd_reset , 24, 0, 0, "reset" }
};
-const unsigned dg100_numcommands = sizeof(dg100_commands) / sizeof(dg100_commands[0]);
struct dynarray16 {
unsigned count; /* number of elements used */
unsigned int i;
/* linear search should be OK as long as dg100_numcommands is small */
- for (i = 0; i < dg100_numcommands; i++) {
- if (dg100_commands[i].id == id) {
- return(&dg100_commands[i]);
+ for (i = 0; i < model->numcommands; i++) {
+ if (model->commands[i].id == id) {
+ return(&model->commands[i]);
}
}
bintime = be_read32(data + i + 8) & 0x7FFFFFFF;
bindate = be_read32(data + i + 12);
creation_time = bintime2utc(bindate, bintime);
- strftime(buf, sizeof(buf), "DG-100 tracklog (%Y/%m/%d %H:%M:%S)",
+ strncpy(buf, model->name, sizeof(buf));
+ strftime(&buf[strlen(model->name)], sizeof(buf)-strlen(model->name), " tracklog (%Y/%m/%d %H:%M:%S)",
gmtime(&creation_time));
*track = route_head_alloc();
(*track)->rte_name = buf;
- (*track)->rte_desc = "DG-100 GPS tracklog data";
+ (*track)->rte_desc = "GPS tracklog data";
track_add_head(*track);
}
/* communication functions */
static size_t
-dg100_send(uint8_t cmd, const void* payload, size_t count)
+dg100_send(uint8_t cmd, const void* payload, size_t param_len)
{
uint8_t frame[FRAME_MAXLEN];
uint16_t checksum, payload_len;
- size_t framelen, param_len;
+ size_t framelen;
int n;
- param_len = count;
- payload_len = 1 + count;
+ payload_len = 1 + param_len;
/* Frame length calculation:
* frame start sequence(2), payload length field(2), command id(1),
* param(variable length),
* checksum(2), frame end sequence(2) */
- framelen = 2 + 2 + 1 + count + 2 + 2;
+ framelen = 2 + 2 + 1 + param_len + 2 + 2;
assert(framelen <= FRAME_MAXLEN);
/* create frame head + command */
frame[4] = cmd;
/* copy payload */
- memcpy(frame + 5, payload, count);
+ memcpy(frame + 5, payload, param_len);
/* create frame tail */
checksum = dg100_checksum(frame + 4, framelen - 8);
/* Frame length calculation:
* frame start sequence(2), payload length field(2), command id(1),
* param(variable length),
- * payload end seqence(2 or 0), checksum(2), frame end sequence(2) */
+ * payload end sequence(2 or 0), checksum(2), frame end sequence(2) */
frame_len = 2 + 2 + 1 + param_len + ((model->has_payload_end_seq) ? 2 : 0) + 2 + 2;
if (frame_len > FRAME_MAXLEN) {
} while (nextheader != 0);
}
+static void
+dg100_getconfig()
+{
+ uint8_t answer[45];
+
+ dg100_request(dg100cmd_getconfig, NULL, answer, sizeof(answer));
+}
+
static void
dg100_getfile(int16_t num, route_head** track)
{
filenum = headers.data[i];
dg100_getfile(filenum, &track);
}
+ dg100_getconfig(); // To light on the green LED on the DG-200
}
static int
static void
dg100_rd_init(const char* fname)
{
- static const model_t dg100_model = { 115200, 1, 1 };
+ static const model_t dg100_model = { "DG-100", 115200, 1, 1, dg100_commands, sizeof(dg100_commands) / sizeof(struct dg100_command) };
model = &dg100_model;
common_rd_init(fname);
}
static void
dg200_rd_init(const char* fname)
{
- static const model_t dg200_model = { 230400, 0, 0 };
+ static const model_t dg200_model = { "DG-200", 230400, 0, 0, dg200_commands, sizeof(dg200_commands) / sizeof(struct dg100_command) };
model = &dg200_model;
common_rd_init(fname);
}
/**************************************************************************/
-// capabilities below means: we can only read tracks
+// capabilities below means: we can read tracks and waypoints
ff_vecs_t dg100_vecs = {
ff_type_serial,
{
- ff_cap_none /* waypoints */,
+ ff_cap_read /* waypoints */,
ff_cap_read /* tracks */,
ff_cap_none /* routes */
},
ff_vecs_t dg200_vecs = {
ff_type_serial,
{
- ff_cap_none /* waypoints */,
+ ff_cap_read /* waypoints */,
ff_cap_read /* tracks */,
ff_cap_none /* routes */
},